Categorical Encoding 將類別變數(categorical variables/features)的字串(strings)或標籤(labels)轉換為數字。
類別變數(categorical variables)可分為兩種:名目變數(Nominal variables)和順序變數(Ordinal variables)。
名目變數(Nominal variables):變數下含有個以上的類別,但類別之間並沒有順序關係,例如:性別變數可分為 male和 female 兩類。
順序變數(Ordinal variables):變數下的類別彼此之間有順序或等級(level)關係,例如:尺吋變數可分為 low, medium 和 high。
將使用這個data-frame,有兩個獨立變數或特徵(features)和一個標籤(label or Target),共有十筆資料。
import pandas as pd
import numpy as np
Data = {'Temperature': ['Hot','Cold','Very Hot','Warm','Hot','Warm','Warm','Hot','Hot','Cold'],
'Color': ['Red','Yellow','Blue','Blue','Red','Yellow','Red','Yellow','Yellow','Yellow'],
'Target':[1,1,1,0,1,0,1,0,1,1]}
df = pd.DataFrame(Data, columns = ['Temperature', 'Color', 'Target'])
One hot encoding (OHE)為變數的每一個種類建立一個二元變數(binary variable),資料對應的類別則顯示1,否則顯示0。這個方法適合線性模型。但是假如變數內的類別很多時,這個方法會增加許多新的features;而且這些新增的變數(或features)可能有相當高的關聯性。
使用Pandas的get_dummies函數(function)轉換:
df = pd.get_dummies(df, prefix=['Temp'], columns=['Temperature'])
df
使用Scikit-learn的OneHotEncoder函數(function)轉換:
from sklearn.preprocessing import OneHotEncoder
ohc = OneHotEncoder()
ohe = ohc.fit_transform(df.Temperature.values.reshape(-1,1)).toarray()
dfOneHot = pd.DataFrame(ohe, columns=["Temp_"+str(ohc.categories_[0][i])
for i in range(len(ohc.categories_[0]))])
dfh = pd.concat([df, dfOneHot], axis=1)
dfh
每個類別出現在資料集的總和(count)或出現的頻率(frequency or percentage)取代每個類別的值。例如:假如100 個資料中有10個是藍色,那我們就以10或0.1取代藍色。這個方法展示每個類別的代表性。
for col in df.columns[:2]:
print(col, ':', len(df[col].unique()), ' labels')
Temperature : 4 labels
Color : 3 labels
df.to_numpy()
color_freq_map = df.Color.value_counts().to_dict()
color_freq_map
{'Blue': 2, 'Red': 3, 'Yellow': 5}
df.Color = df.Color.map(df_map)
df
以在目標(target)變數的某一類別的平均值取代變數的每一類別。假如我們有一個 “city” 的類別變數,我們想預測顧客是否買電視,假如百分之三十的“Taipei”人買電視,我們將以0.3取代“Taipei”。
這個方法有三個優點:不會擴張feature的空間;取得了類別轉換時關於目標(target)變數的資訊;建立了變數和目標(target)變數的單調關係,這個單調關係往往會改善線性模型的效果。
X = df.drop(['Target'], axis=1)
y = df['Target']
import category_encoders as ce
ce_target = ce.TargetEncoder(cols=['Color'])
ce_target.fit(X,y)
ce_target.transform(X, y)